precision mediump float;

uniform sampler2D s_texture;
uniform sampler2D shadow_texture;

uniform samplerCube reflection_texture;

uniform vec3 sun_vector;

uniform mat4 uSunPMatrix;

uniform vec3 cube_map_pos;

uniform mat4 cubemap_matrix;

uniform float Kd;
uniform float Ka;

varying vec2 aVertexUVs_;
varying vec3 aVertexNormal_;
varying vec3 aVertexMNormal_;
varying vec4 shadow_coord_;

varying vec3 aVertexPosition_;

float unpack_depth(const in vec4 rgba_depth)
{
    const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);
	//const vec4 bit_shift = vec4(1.0, 1.0/(255.0), 1.0/(255.0*255.0), 1.0/(255.0*255.0*255.0));
    float depth = dot(rgba_depth, bit_shift);
    return depth;
}


vec4 UnPackRGBA(const in float depth)
{
    vec4 bit_shift = vec4(1.0, 128.0, (128.0*128.0), (128.0*128.0*128.0));
    vec4 bit_mask  = vec4(1.0/128.0, 1.0/128.0, 1.0/128.0, 0.0);
    vec4 res = fract(depth * bit_shift);
	
	
    res -= (res.yzww * bit_mask);
	res[3] += 9.0/128.0;
	//res.w *= 200.0;

    return res;
}

vec4 EncodeFloatRGBA( float vv )
{
    vec4 kEncodeMul = vec4(160581375.0, 65025.0, 255.0, 1.0);
    float kEncodeBit = 1.0/255.0;
	float v = vv;
    vec4 enc = kEncodeMul * v;
    enc = fract(enc);
    enc -= enc.xyzz * kEncodeBit;
    return enc;
}



void main(void) {
    
	vec2 poissonDisk[4];

	poissonDisk[0] = vec2( -0.94201624, -0.39906216 );
	poissonDisk[1] = vec2( 0.94558609, -0.76890725 );
	poissonDisk[2] = vec2( -0.094184101, -0.92938870 );
	poissonDisk[3] = vec2( 0.34495938, 0.29387760 );

	vec4 shad_coord_;
	
	//shad_coord_[0] = (shadow_coord_[0]/shadow_coord_[3])* 0.5 + 0.5;
	shad_coord_[0] = shadow_coord_[0];
	//shad_coord_[1] = (shadow_coord_[1]/shadow_coord_[3])* 0.5 + 0.5;
	shad_coord_[1] = shadow_coord_[1];
	shad_coord_[2] = shadow_coord_[2];

	float visibility = 1.0;
	
	shad_coord_[2] = shad_coord_[2]*0.5 + 0.5;
	
		
	float dot_product  = sun_vector[0] * aVertexNormal_[0] + sun_vector[1] * aVertexNormal_[1] + sun_vector[2] * aVertexNormal_[2];
	dot_product = clamp(dot_product, 0.0, 1.0);
	float bias = 0.000008*tan(acos(dot_product));
	bias = clamp(bias, 0.0,0.00001);
	
	if(shad_coord_[1] < (-1.0 + 2.0/27.0))
	{
		shad_coord_[0] = (shad_coord_[0] + 0.0/27.0)*27.0;
		shad_coord_[1] = (shad_coord_[1] + 26.0/27.0)*27.0;
		shad_coord_[0] = shad_coord_[0] * 0.25 + 0.25;
		shad_coord_[1] = shad_coord_[1] * 0.25 + 0.25;//0.247;
		
	}else
	if(shad_coord_[1] < (-1.0 + 6.0/27.0))
	{
		shad_coord_[0] = (shad_coord_[0] + 0.0/27.0)*9.0;
		shad_coord_[1] = (shad_coord_[1] + 23.0/27.0)*13.5;
		shad_coord_[0] = shad_coord_[0] * 0.25 + 0.749;
		shad_coord_[1] = shad_coord_[1] * 0.25 + 0.25;
		bias *= 1.5;
	}else
	if(shad_coord_[1] < (-1.0 + 18.0/27.0))
	{
		shad_coord_[0] = (shad_coord_[0] + 0.0/27.0)*3.0;
		shad_coord_[1] = (shad_coord_[1] + 15.0/27.0)*(27.0/5.5);
		shad_coord_[0] = shad_coord_[0] * 0.25 + 0.25;
		shad_coord_[1] = shad_coord_[1] * 0.25 + 0.79;
		bias *= 2.5;
	}else
	{
		shad_coord_[0] = (shad_coord_[0] + 0.0/27.0)*1.0;
		shad_coord_[1] = (shad_coord_[1] - 9.0/27.0)*(27.0/18.0);
		shad_coord_[0] = shad_coord_[0] * 0.25 + 0.75;
		shad_coord_[1] = shad_coord_[1] * 0.25 + 0.751;
		bias *= 4.5;
	}
	


	for (int i=0;i<4;i++)
	{
		if(unpack_depth(texture2D( shadow_texture, shad_coord_.xy + poissonDisk[i]/1600.0 )) < shad_coord_[2] - bias)
		{
			//visibility-=0.058;
			//visibility-=0.058823529411764705;
			visibility-=0.25;
		}
	}

visibility = 1.0;

	dot_product = clamp(dot_product * visibility, 0.0, 1.0);
	vec4 diffuse_light = vec4(dot_product, dot_product, dot_product, 1.0);

	dot_product = 1.0;

	vec4 ambient_light = UnPackRGBA(Ka)*vec4(0.1, 0.1, 0.1, 1.0);
	vec4 texture_color;
	
	if(ambient_light.w > 0.5)
		texture_color = texture2D( s_texture, aVertexUVs_ );
	else
		texture_color = vec4(1.0);

	ambient_light.w = 1.0;
		
	//vec4 diffuse = UnPackRGBA(Kd)*(diffuse_light + ambient_light) * texture_color;
	
	vec4 diffuse = UnPackRGBA(Kd)*pow(diffuse_light + ambient_light, vec4(1.0 / 2.2)) * texture_color;
	
	gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);

	//gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));
	//gl_FragColor = UnPackRGBA(Kd);

	
	
	}
